PostgreSQLの珍しい実行計画はAurora DSQLでも出現するのか確認してみた
リテールアプリ共創部@大阪の岩田です。
以前Zennで読んだ以下の記事が「面白いな〜」と印象に残っていたのですが、これらの実行計画はAurora DSQLでも利用可能なのか気になったので試してみました。
やってみる
それではさっそく試していきましょう。以下のSQLは全てadminユーザーで実行しています。
テーブルの作成
まず元記事にならって以下のDDLでテーブルを作成します。
create table hoge (id int primary key, val int);
準備ができたら色々SELECT文を実行していきます。
10位: LockRows
まずはLockRowsを試してみましょう。
explain select * from hoge for update;
実行すると以下のエラーが出ました。
ERROR: locking clause such as FOR UPDATE can be applied only on tables with equality predicates on the key
エラーメッセージからするとキーを指定すればいけそうですね。このエラーについては以下のAWSブログでも紹介されていました。
ということでWHERE句を追加してリトライしてみました。
explain select * from hoge where id = 1 for update;
結果は以下の通りです。
QUERY PLAN
---------------------------------------------------------------------------------
LockRows (cost=100.17..208.19 rows=1 width=24)
-> Index Scan using hoge_pkey on hoge (cost=100.17..208.18 rows=1 width=24)
Index Cond: (id = 1)
Projected via pushdown compute engine: id, val
(4 rows)
LockRows
が出現しました!Aurora DSQLは楽観的同時実行制御を利用するためロックは取得しないはずなのですが、実行計画としてはLockRorws
が存在するようです。この実行計画が現れた場合はミスリードしないように注意が必要そうです。
9位: Sample Scan
続いてSample Scanです。
explain select * from hoge tablesample system(10);
結果は以下の通りでした。
ERROR: Sampling is not supported
Aurora DSQLではサンプリングの機能がサポートされていないようです。
8位: MixedAggregate
続いてMixedAggregateです。
explain select id from hoge group by grouping sets(id, ());
結果は以下の通りでした。
QUERY PLAN
-------------------------------------------------------------------------------------------------
GroupAggregate (cost=125100.05..183600.06 rows=1000001 width=4)
Group Key: id
Group Key: ()
-> Index Only Scan using hoge_pkey on hoge (cost=125100.05..171100.05 rows=1000000 width=4)
Projected via pushdown compute engine: id
(5 rows)
クエリはエラーなく実行できましたが、実行計画にMixedAggregate
は出現しませんでした。
7位: HashSetOp
続いてHashSetOpです。
explain select id from hoge except select id from fuga;
実行結果は以下の通りでした。
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
HashSetOp Except (cost=125100.05..377200.10 rows=1000000 width=8)
-> Append (cost=125100.05..372200.10 rows=2000000 width=8)
-> Subquery Scan on "*SELECT* 1" (cost=125100.05..181100.05 rows=1000000 width=8)
-> Index Only Scan using hoge_pkey on hoge (cost=125100.05..171100.05 rows=1000000 width=4)
Projected via pushdown compute engine: id
-> Subquery Scan on "*SELECT* 2" (cost=125100.05..181100.05 rows=1000000 width=8)
-> Index Only Scan using fuga_pkey on fuga (cost=125100.05..171100.05 rows=1000000 width=4)
Projected via pushdown compute engine: id
(8 rows)
HashSetOp
が出現しました!なんか嬉しいです。
6位: Table Function Scan
続いてTable Function Scanです。
explain
select *
from xmltable(
'/rows/row'
passing
$$
<rows>
<row id="1"></row>
</rows>
$$
columns id int path '@id'
);
実行結果は以下の通りでした。
ERROR: unsupported XML feature
LINE 6: $$
^
DETAIL: This functionality requires the server to be built with libxml support.
xmltableがサポートされていないようです。
5位: Foreign Update
続いてForeign Updateです。まずpostgres_fdw
を利用可能にするところからです。
create extension postgres_fdw;
実行結果は以下の通りでした。
ERROR: unsupported statement: CreateExtension
公式ドキュメントにも記載されていますがAurora DSQLはCREATE EXTENSIONに未対応とのことです。
4位: Foreign Delete
Foreign Updateと同様にForeign Data WrapperがサポートされていないためAurora DSQLではこの実行計画が出現することはできなさそうです。
3位: Tid Range Scan
続いてTid Range Scanです。
insert into hoge select generate_series(1,10000);
analyze hoge;
explain select * from hoge where ctid < '(1,0)';
実行結果は以下の通りでした。
ERROR: cannot retrieve a system column in this context
Aurora DSQLではPostgreSQLと違ってctidという概念が無いのかもしれません。一応以下のSQLも試してみます。
select ctid from hoge where id = 1;
結果は変わらず以下の通りでした。
ERROR: cannot retrieve a system column in this context
そもそもAurora DSQLにはctid
という概念が存在しないのか、それともユーザーには隠蔽されているだけなのか...この辺は内部実装の妄想が捗って面白いですね。
ちょっと脱線しますがOIDという概念はあるのか気になったので、こちらも試してみました。
SELECT oid, relname, relnamespace, relowner FROM pg_class;
結果は以下の通りでした。
oid | relname | relnamespace | relowner
-------+------------------------------------------------+--------------+----------
1247 | pg_type | 11 | 10
1249 | pg_attribute | 11 | 10
1255 | pg_proc | 11 | 10
...略
この辺は通常のPostgreSQLと同じなんですね。
2位: Foreign Insert
Foreign Updateと同様に...(以下略)
1位: Named Tuplestore Scan
最後はNamed Tuplestore Scanです。まずユーザー定義関数の作成を試みます。
create function copy_inserted() returns trigger as $$
begin
if (tg_op = 'INSERT') then
execute 'insert into fuga select * from new_table';
end if;
return null;
end;
$$
language plpgsql;
結果は以下の通りでした。
ERROR: CREATE FUNCTION with language plpgsql not supported
Aurora DSQLではユーザー定義関数が使えないようです。
とりあえず文法的に通るか確認するためにトリガーの作成も試みました。
create trigger copy_hoge_insert_to_fuga
after insert on hoge
referencing new table as new_table
for each statement execute procedure copy_inserted();
結果は以下の通りでした。
ERROR: unsupported statement: CreateTrig
create trigger
を実行したのですが、CreateTrig
はサポートしてないというエラーが出ました。SQLのパースに失敗してるんですかね?まあいずれにせよ公式ドキュメントにもトリガーは未サポートと記載してあるので実行計画にNamed Tuplestore Scanが出現することは無さそうです。
まとめ
PostgreSQLの珍しい実行計画がAurora DSQLにも出現するのか確認してみました。今回の検証では以下の実行計画のみ出現を確認できました。
- LockRows
- HasSetOp
その他の実行計画については前提となる機能がAurora DSQLではサポートいないなどの理由から出現を確認できませんでした。今後GAまでに追加の機能サポートがあれば今回出現しなかった実行計画も確認できるようになるかもしれませんね。いずれにせよAurora DSQLとPostgreSQLの互換性について確認する良い機会になりました。みなさんもぜひ色々なSQLを試して理解を深めてみて下さい。